package utils

import (
	"a_plus_station/tables"
	"context"
	"fmt"
	"github.com/go-redis/redis/v8"
	"gorm.io/gorm"
	"time"
)

type CollectCache struct {
	RedisClient *redis.Client
}

func NewCollectCache(addr string, password string, db int) *CollectCache {
	rdb := redis.NewClient(&redis.Options{
		Addr:     addr,
		Password: password,
		DB:       db,
	})

	return &CollectCache{
		RedisClient: rdb,
	}
}

// 检查用户是否收藏了某商品
func (cc *CollectCache) IsCollected(userID int32, goodsID string) (bool, error) {
	ctx := context.Background()
	key := getUserCollectsKey(userID)

	// 使用 ZScore 检查成员是否存在
	score, err := cc.RedisClient.ZScore(ctx, key, goodsID).Result()

	// 如果分数存在且大于0，表示已收藏
	if err == redis.Nil {
		return false, nil // 成员不存在
	} else if err != nil {
		return false, err // 其他错误
	}

	return score > 0, nil
}

// 添加收藏
func (cc *CollectCache) AddCollect(userID int32, goodsID string) error {
	ctx := context.Background()
	key := getUserCollectsKey(userID)

	// 使用当前时间作为分数（Unix时间戳秒）
	score := float64(time.Now().Unix())

	// 添加成员并设置分数
	_, err := cc.RedisClient.ZAdd(ctx, key, &redis.Z{
		Score:  score,
		Member: goodsID,
	}).Result()

	if err != nil {
		return err
	}

	// 更新过期时间
	return cc.RedisClient.Expire(ctx, key, 24*time.Hour).Err()
}

// 移除收藏
func (cc *CollectCache) RemoveCollect(userID int32, goodsID string) error {
	ctx := context.Background()
	key := getUserCollectsKey(userID)

	// 从有序集合中移除成员
	_, err := cc.RedisClient.ZRem(ctx, key, goodsID).Result()
	return err
}

// 分页获取用户收藏商品ID
func (cc *CollectCache) GetUserCollectsPaged(db *gorm.DB, userID int32, page, pageSize int32) ([]string, int64, error) {
	ctx := context.Background()
	key := getUserCollectsKey(userID)

	// 检查缓存是否存在
	exists, err := cc.RedisClient.Exists(ctx, key).Result()
	if err != nil {
		return nil, 0, err
	}

	if exists == 0 {
		// 假设db是全局的*gorm.DB
		if err := cc.loadFromDB(db, userID); err != nil {
			return nil, 0, err
		}
	}

	// 获取总数
	total, err := cc.RedisClient.ZCard(ctx, key).Result()
	if err != nil {
		return nil, 0, err
	}

	// 计算分页范围
	start := (page - 1) * pageSize
	stop := start + pageSize - 1

	// 按分数倒序获取（最新收藏在前）
	ids, err := cc.RedisClient.ZRevRange(ctx, key, int64(start), int64(stop)).Result()
	return ids, total, err
}

// 从数据库加载收藏到Redis有序集合
func (cc *CollectCache) loadFromDB(db *gorm.DB, userID int32) error {
	var collects []tables.Collect
	err := db.Where("user_id = ?", userID).Find(&collects).Error
	if err != nil {
		return err
	}

	ctx := context.Background()
	key := getUserCollectsKey(userID)
	pipe := cc.RedisClient.Pipeline()

	// 批量添加收藏商品
	for _, collect := range collects {
		// 使用收藏时间作为分数
		score := float64(collect.CreatedAt.Unix())
		goodsID := collect.GoodsID

		pipe.ZAdd(ctx, key, &redis.Z{
			Score:  score,
			Member: goodsID,
		})
	}

	// 设置24小时过期时间
	pipe.Expire(ctx, key, 24*time.Hour)
	_, err = pipe.Exec(ctx)
	return err
}

// 辅助函数：获取用户收藏键名
func getUserCollectsKey(userID int32) string {
	return fmt.Sprintf("user:%d:collects", userID)
}
